<template>
  <div>
    <el-drawer
      v-model="visiable"
      direction="rtl"
      size="80%"
      :before-close="handlerClose"
      :title="title"
      ref="articleDrawer"
    >
      <el-form
        :model="form"
        label-position="top"
        style="margin:10px 10px 50px 10px;"
        :rules="rules"
        ref="formRef"
      >
        <el-form-item label="标题" prop="title">
          <el-input v-model="form.title" placeholder="请输入标题"></el-input>
        </el-form-item>
        <el-form-item label="摘要">
          <el-input v-model="form.summary" placeholder="请输入导语" type="textarea" :rows="2"></el-input>
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="状态" prop="status">
              <el-radio v-model="form.status" label="0">发布</el-radio>
              <el-radio v-model="form.status" label="1">不发布</el-radio>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="是否评论" prop="isComment">
              <el-radio v-model="form.isComment" label="0">是</el-radio>
              <el-radio v-model="form.isComment" label="1">否</el-radio>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="排序" prop="sort">
              <el-input-number v-model="form.sort" :min="1"></el-input-number>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="请选择文章分类" prop="classifyIds">
              <el-cascader
                :options="classify"
                v-model="form.classifyIds"
                :props="props"
                placeholder="请选择"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="标签" prop="tagIds">
              <el-select
                v-model="form.tagIds"
                placeholder="请选择文章标签"
                multiple
                filterable
                allow-create
                default-first-option
                :reserve-keyword="false"
              >
                <el-option
                  v-for="item in tag"
                  :key="item.tagId"
                  :label="item.name"
                  :value="item.tagId"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row align="middle">
          <el-col :span="6">
            <el-form-item label="封面图">
              <el-upload
                class="cover-uploader"
                :action="upload.action"
                :headers="upload.headers"
                :show-file-list="false"
                :on-success="uploadSuccess"
                :before-upload="beforeUpload"
              >
                <img v-if="coverUrl" :src="coverUrl" class="cover" />
                <el-icon v-else class="cover-uploader-icon">
                  <plus />
                </el-icon>
              </el-upload>
            </el-form-item>
          </el-col>
          <el-col :span="10">
            <el-input v-model="urlInput" placeholder="图片url">
              <template #append>
                <el-popover
                  placement="top-start"
                  :width="200"
                  content="请黏贴图片路径"
                  v-model:visible="visible"
                >
                  <template #reference>
                    <el-button type="info" @click="showPic">展示</el-button>
                  </template>
                </el-popover>
              </template>
            </el-input>
          </el-col>
        </el-row>
        <el-form-item label="内容">
          <md-editor
            v-model="form.content"
            :toolbars-exclude="toolBarsExclude"
            @upload-img="onUploadImg"
          />
        </el-form-item>
      </el-form>
      <div class="my-drawer__footer">
        <el-button @click="cancelClick">取消</el-button>
        <el-button
          type="primary"
          @click="confirmClick(formRef)"
          :loading="addLoading"
        >{{ addLoading ? '保存中 ...' : '保存' }}</el-button>
      </div>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from 'vue'
import type { Article } from '@/api/types/article'
import type { Tag } from '@/api/types/tag'
import MdEditor from 'md-editor-v3'
import 'md-editor-v3/lib/style.css';
import { getClassifyTree } from '@/api/classify'
import { getTagList } from '@/api/tag'
import { uploadMd } from '@/api/upload'
import { getToken } from '@/utils/auth'
import { UploadFile } from 'element-plus/es/components/upload/src/upload.type';
import type { ElDrawer, ElForm } from 'element-plus'
import { add, update, getById } from '@/api/article'

type FormInstance = InstanceType<typeof ElForm>
const formRef = ref<FormInstance>()

const visiable = ref(false)

const articleDrawer = ref<InstanceType<typeof ElDrawer>>()

const picUrl = import.meta.env.VITE_SERVICE_BASE_URL

const visible = ref(false)

const form = reactive<Article>({
  articleId: undefined,
  title: '',
  summary: '',
  isComment: '1',
  status: '1',
  sort: 1,
  classifyIds: [0],
  tagIds: [],
  thumbnail: undefined,
  content: ''
})

const coverUrl = ref()

const urlInput = ref('')

const toolBarsExclude = [
  'github'
]

const title = ref('')

const addLoading = ref(false)

const rules = reactive({
  title: [
    {
      required: true,
      message: '请输入标题',
      trigger: 'blur'
    }
  ],
  isComment: [
    {
      required: true,
      message: '请选择是否评论',
      trigger: 'blur'
    }
  ],
  status: [
    {
      required: true,
      message: '请选择状态',
      trigger: 'blur'
    }
  ],
  sort: [
    {
      required: true,
      message: '请排序',
      trigger: 'blur'
    }
  ],
  classifyId: [
    {
      required: true,
      message: '请选择目录',
      trigger: 'blur'
    }
  ],
})

const classify = ref<[]>()

const tag = ref<Tag[]>()

const upload = ref({
  action: picUrl + '/admin/upload/cover/picture',
  headers: new Headers({
    'Authorization': "Bearer " + getToken()
  })
})

/**
 * 表单加载选项
 */
const props = {
  multiple: true,
  checkStrictly: true,
  emitPath: false
}

const emit = defineEmits(['refreshArticle'])

onMounted(() => {
  loadClassifyTree()
  loadTagList()
})

/**
 * 加载对话框树结构选择
 */
const loadClassifyTree = async () => {
  classify.value = await getClassifyTree(0)
}

/**
 * 加载标签列表
 */
const loadTagList = async () => {
  tag.value = await getTagList()
}

/**
 * 上传图片
 */
const onUploadImg = async (files: FileList, callback: (urls: string[]) => void) => {
  const res = await Promise.all<string>(
    Array.from(files).map((file) => {
      return new Promise(async (rev, rej) => {
        const form = new FormData();
        form.append('file', file)
        await uploadMd(form).then((res) => rev(res)).catch((error) => rej(error));
      })
    })
  )
  callback(res.map((item: string) => {
    return picUrl + item
  }))
}

/**
 * 打开对话框
 * @param article 
 */
const openForm = async (article?: Article) => {
  if (article === undefined) {
    title.value = '新增文章'
  } else if (article.articleId) {
    const articleById = await getById(article.articleId)
    form.articleId = articleById.articleId
    form.title = articleById.title
    form.summary = articleById.summary
    form.isComment = articleById.isComment
    form.status = articleById.status
    form.sort = articleById.sort
    form.classifyIds = articleById.classifyIds
    form.tagIds = articleById.tagIds
    form.thumbnail = articleById.thumbnail
    form.content = articleById.content
    title.value = '修改文章'
    showCover(articleById.thumbnail)
  }
  visiable.value = true
}

const showCover = (url: string | undefined) => {
  let web = url?.indexOf('http')
  if (web === -1) {
    coverUrl.value = picUrl + url
  } else if (web === 0) {
    coverUrl.value = url
  }
}

const showPic = () => {
  if (urlInput.value.length > 0) {
    visible.value = false
    showCover(urlInput.value)
  } else {
    visible.value = true
  }
}

/**
 * 关闭对话框
 * @param done 
 */
const handlerClose = (done: () => void) => {
  ElMessageBox.confirm('是否放弃编辑', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
  })
    .then(() => {
      done()
      refreshForm()
    })
    .catch(() => {
      // catch error
    })
}

/**
 * 上传成功
 * @param response 
 * @param file 
 */
const uploadSuccess = (response: string, file: UploadFile) => {
  form.thumbnail = response;
  showCover(response)
  ElMessage({
    message: '上传成功',
    type: 'success',
  })
}

/**
 * 上传前校验
 * @param file 
 */
const beforeUpload = (file: any) => {
  const isJPG = file.type === 'image/jpeg';
  const isPNG = file.type === 'image/png';
  const isLt2M = file.size / 1024 / 1024 < 5;
  if (!isJPG && !isPNG) {
    ElMessage({
      message: '上传头像图片只能是 JPG或PNG 格式!',
      type: 'error',
    })
  }
  if (!isLt2M) {
    ElMessage({
      message: '上传头像图片大小不能超过 5MB!',
      type: 'error',
    })
  }
  return (isJPG || isPNG) && isLt2M;
}

/**
 * 关闭对话框
 */
const cancelClick = () => {
  articleDrawer.value!.handleClose()
}

/**
 * 提交表单
 */
const confirmClick = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  const valid = await formEl.validate()
  if (!valid) return false
  let ok
  let message
  if (form.articleId) {
    message = '修改成功'
    ok = await update(form)
  } else {
    message = '添加成功'
    ok = await add(form)
  }
  emit('refreshArticle')
  visiable.value = false
  loadTagList()
  refreshForm()
  if (ok) {
    ElMessage({
      message,
      type: 'success',
    })
  }
}

const refreshForm = () => {
  form.title = ''
  form.summary = ''
  form.isComment = '1'
  form.status = '1'
  form.sort = 1
  form.classifyIds = [0]
  form.tagIds = []
  form.thumbnail = undefined
  form.content = ''
  coverUrl.value = undefined
}

defineExpose({
  openForm
})
</script>

<style lang="sass" scoped>

.el-select
  width: 100%

.cover-uploader
  border: 1px dashed #d9d9d9
  border-radius: 6px
  cursor: pointer
  position: relative

.cover-uploader:hover
  border-color: #409eff

.cover-uploader-icon
  font-size: 28px
  color: #8c939d
  width: 178px
  height: 178px
  text-align: center

.cover
  width: 178px
  height: 178px
  display: block

.my-drawer__footer
  padding: 10px 0px 10px 0px
  position: absolute
  bottom: 0
  background-color: white
  width: 100%
  z-index: 10
  text-align: right
  padding-right: 50px
  .el-button
    width: 100px
</style>